import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import FileSaver from 'file-saver'
import mitt from 'mitt'
import moment from 'moment'
import AMapLoader from '@amap/amap-jsapi-loader'
import convert from 'color-convert'
import router  from '@/router'
import store from '@/store'
import { getSystemConfigStorage, getAdminToken } from "@/utils/storages"

// 创建事件总线
const emitter = mitt()

let common = {
    appPageSize: getSystemConfigStorage() && getSystemConfigStorage().pageSize || window.configs.pageSize || 20,
    appPageSizes: [10, 20, 30, 50, 100],
    globalZindex: 10000, // 全局z-index
    globalLayoutTypes: [1, 2, 3, 4], // 全局布局类型
    fullLoadings: null,
    maxExportCount: window.configs.baseExportCount || 20000, // 最大可导出数量
    maxExportTips: `不允许导出超过${window.configs.baseExportCount || 20000}条数据，如有需要，请联系管理员处理!`,
    uploadBaseUrl: (() => {
        let baseApi = ""
        if (import.meta.env.MODE === 'development') {
            baseApi = window.configs.baseTestApi
        } else if (import.meta.env.MODE === 'production') {
            if (import.meta.env.VITE_APP_FLAG === 'pro') {
                baseApi = window.configs.baseApi
            } else if (import.meta.env.VITE_APP_FLAG === 'uat') {
                baseApi = window.configs.baseUatApi
            } else if (import.meta.env.VITE_APP_FLAG === 'test') {
                baseApi = window.configs.baseTestApi
            } else {
                baseApi = window.configs.baseApi
            }
        }
        return baseApi
    })(),
    uploadHeaders: () => {
        return { 
            'Authorization': 'bearer ' + getAdminToken() 
        }
    },
    /* 全局loading */
    fullLoading() {
        common.closeFullLoading(true)
        setTimeout(() => {
            common.fullLoadings = ElLoading.service({
                lock: true,
                fullscreen: true,
                text: "Loading...",
                spinner: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728=""><path fill="currentColor" d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32m0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32m448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32m-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32M195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0m-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z"></path></svg>`,
                background: "rgba(0,0,0,0.7)",
                customClass: "c-el-loading"
            })
        }, 0)
    },
    closeFullLoading(immediately) {
        if (immediately) {
            common.execCloseFullLoading()
        } else {
            setTimeout(() => {
                common.execCloseFullLoading()
            }, 10);
        }
    },
    execCloseFullLoading() {
        if (common.fullLoadings) {
            common.fullLoadings.close()
        }
    },
    // 发送广播信息
    setBroadcast(bdName, data) {
        emitter.emit(bdName, data)
    },
    // 接收广播信息
    getBroadcast(bdName, optionsName, callback) {
        try {
            emitter.on(bdName, res => {
                // 名称相同才执行
                if (res.name.indexOf(optionsName) != -1) {
                    if (callback) {
                        try {
                            callback(res)
                        } catch(ex) {
                            console.error("接收广播后执行方法报错：" + ex)
                        }
                    }
                }
            })
        } catch(e) {
            console.error("接收广播报错：" + e)
        }
    },
    // axios blob方式下载文件
    blobDownload(res, name) {
        let blob = new Blob([res], { type: res.type })
        let downloadElement = document.createElement('a')
        let href = window.URL.createObjectURL(blob); //创建下载的链接
        downloadElement.href = href;
        downloadElement.download = name; //下载后文件名
        document.body.appendChild(downloadElement);
        downloadElement.click(); //点击下载
        document.body.removeChild(downloadElement); //下载完成移除元素
        window.URL.revokeObjectURL(href); //释放blob对象
    },
    /* 获取document.body.getBoundingClientRect()对象 */
    getBoundingClient() {
        return document.body.getBoundingClientRect()
    },
    /* MessageBox重写 */
    configBox(content, title, options) {
        options = options || {}
        options.autofocus = options.autofocus || false
        options.title = title || "提示"
        options.message = content || ""
        options.type = options.type || "warning"
        options.customClass = options.customClass || ""
        options.draggable = options.draggable === false ? false : true
        options.showClose = options.showClose === false ? false : true
        return options
    },
    alert(content, title, options) {
        options = common.configBox(content, title, options)
        return ElMessageBox.alert(content, options)
    },
    confirm(content, title, options) {
        options = common.configBox(content, title, options)
        return ElMessageBox.confirm(content, options)
    },
    prompt(content, title, options) {
        options = common.configBox(content, title, options)
        options.type = ""
        return ElMessageBox.prompt(content, options)
    },
    msgbox(content, title, options) {
        options = common.configBox(content, title, options)
        return ElMessageBox.msgbox(options)
    },
    /* Message重写 */
    configMessage(content, options) {
        options = options || {}
        options.message = content || ""
        options.type = options.type || "info"
        options.duration = options.duration || 2500
        options.offset = options.offset || 20
        options.dangerouslyUseHTMLString = options.dangerouslyUseHTMLString || false
        options.showClose = options.showClose || false
        options.center = options.center || false
        options.customClass = options.customClass || ""
        options.grouping = options.grouping === false ? false : true
        if (options.onClose && typeof(options.onClose) === "function") {
            options.onClose
        }
        return options
    },
    infoMsg(content, options) {
        options = common.configMessage(content, options)
        options.type = "info"
        return ElMessage(options)
    },
    successMsg(content, options) {
        options = common.configMessage(content, options)
        options.type = "success"
        return ElMessage(options)
    },
    warningMsg(content, options) {
        options = common.configMessage(content, options)
        options.type = "warning"
        return ElMessage(options)
    },
    errorMsg(content, options) {
        options = common.configMessage(content, options)
        options.type = "error"
        return ElMessage(options)
    },
    /* 表格自动格式化日期 */
    tableDateFormat(row, column) {
        var date = row[column.property]
        return common.getFormatDate(date)
    },
    // unix时间戳自动格式化为日期
    tableUnixDateFormat(row, column) {
        var date = row[column.property]
        return common.getFormatDate(date, true)
    },
    // 日期时间转换为时间戳
    toUnixStamp(date) {
        return !date ? '' : moment(date).format("X")
    },
    // 根据传的日期时间，转换为指定格式
    getFormatDate(date, isUnix, formatTime) {
        if (isUnix) {
            return !date ? '' : moment.unix(date).format(formatTime || 'YYYY-MM-DD HH:mm:ss')
        } else {
            return !date ? '' : moment(date).format(formatTime || 'YYYY-MM-DD HH:mm:ss')
        }
    },
    // 获取当前日期时间并转换为指定格式
    getFormatDateNow(formatTime) {
        return moment().format(formatTime || 'YYYY-MM-DD HH:mm:ss')
    },
    // 星期几得转换
    getFormatWeek(date, isUnix, isEn, tips) {
        let weekName = ""
        if (!isEn) {
            let week = common.getFormatDate(date, isUnix, "d")
            switch(Number(week)) {
                case 1: week = "一"; break;
                case 2: week = "二"; break;
                case 3: week = "三"; break;
                case 4: week = "四"; break;
                case 5: week = "五"; break;
                case 6: week = "六"; break;
                case 0: week = "日"; break;
            }
            weekName = tips ? `${tips}${week}` : `星期${week}`
        } else {
            weekName = common.getFormatDate(date, isUnix, "dddd")
        }
        return weekName
    },
    // 本地导出文件
    exportCommonFile(data, fileName, suffix, type) {
        try {
            // 将json转换成字符串
            /*if (typeof data == 'object') {
                data = JSON.stringify(data)
            }*/
            data = JSON.stringify(data)
            const blob = new Blob([data], { type: type || "" })
            FileSaver.saveAs(blob, fileName + suffix)
        } catch(e) {
            common.alert("导出数据格式不正确!")
            return false
        }
    },
    // 本地批量导出文件
    exportCommonFiles(datas, fileNames, suffix, type) {
        try {
            window.$Common.fullLoading()
            for (let i in datas) {
                ((i) => {
                    setTimeout(() => {
                        common.exportCommonFile(datas[i], fileNames[i], suffix, type)
                        if (i >= datas.length - 1) {
                            window.$Common.closeFullLoading()
                        }
                    }, (i + 1) * 50);
                })(i)
            }
        } catch(e) {
            common.alert("导出数据格式不正确!")
            return false
        }
    },
    // 上下移动交换顺序
    swiperSort(arr, index1, index2) {
        arr[index1] = arr.splice(index2, 1, arr[index1])[0];
        return arr
    },
    // 操作枚举对象
    getEnumConfigs(key) {
        // 根据key获取当前需要的对象数组
        let temp = {
            arrs: [], // 数组
            objs: {}  // 键值对
        }
        temp.arrs = store.getters.enumConfigs[key]
        for (let i in temp.arrs) {
            let item = temp.arrs[i]
            temp.objs[item.name] = {}
            for (let k in item) {
                if (k != "name") {
                    temp.objs[item.name][k] = item[k]
                }
            }
        }
        return temp
    },
    getEnumConfigsItem(items, name, key) {
        let val = items && items[name] && items[name][key]
        if (typeof val === "string") {
            val = val || ""
        } else {
            val = !val && val !== 0 ? null : val
        }
        return val
    },
    // 时间范围的快捷筛选，设置时间
    setPickerTime(picker, spaceTime, dateStr, isStartOf) {
        let timeArr = []
        let startTime = null
        let endTime = moment().format("YYYY-MM-DD 23:59:59")
        if (isStartOf) {
            startTime = moment().startOf(dateStr).format("YYYY-MM-DD 00:00:00")
        } else {
            startTime = moment().subtract(spaceTime, dateStr).format("YYYY-MM-DD 00:00:00")
            // 因为取值是从0点开始的，所以会多出一天，开始时间需要往后延一天
            startTime = moment(startTime).add(1, "days").format("YYYY-MM-DD 00:00:00")
        }
        timeArr = [startTime, endTime]
        if (picker) {
            picker.$emit('pick', timeArr);
        }
        return timeArr
    },
    // 节流  为了防止用户多次点击
    mxThrottle(fn, gapTime) {
        if (gapTime == null || gapTime == undefined) {
            gapTime = 1500
        }
        let _lastTime = null
        // 返回新的函数
        return function() {
            let _nowTime = +new Date()
            if (_nowTime - _lastTime > gapTime || !_lastTime) {
                // 将this和参数传给原函数
                fn.apply(this, arguments)
                _lastTime = _nowTime
            }
        }
    },
    // 转换分页模式
    mxPageToSkipCount(item) {
        let r = JSON.parse(JSON.stringify(item))
        if (r.page) {
            r.skipCount = (r.page - 1) * r.size
            delete r.page
        }
        if (r.size) {
            r.maxResultCount = r.size
            delete r.size
        }
        return r
    },
    // 将barcode转换为image
    mxSetBarcodeImage(code, name, options) {
        // 创建一个临时的canvas来绘制条形码
        const canvas = document.createElement("canvas")
        const ctx = canvas.getContext("2d")
        const barcode = JsBarcode(canvas, code, {
            format: options && options.format || "CODE128",
            width: options && options.width || 2,
            height: options && options.height || 40,
            displayValue: options && options.displayValue || false,
            fontSize: options && options.fontSize || 13,
            fontOptions: options && options.fontOptions || "",
            font: options && options.font || "monospace",
            textAlign: options && options.textAlign || "center",
            textPosition: options && options.textPosition || "bottom",
            textMargin: options && options.textMargin || 2,
            background: options && options.background || "#ffffff",
            lineColor: options && options.lineColor || "#000000",
            margin: options && options.margin || 10,
            marginTop: options && options.marginTop,
            marginBottom: options && options.marginBottom,
            marginLeft: options && options.marginLeft,
            marginRight: options && options.marginRight
        })
        // 将canvas转换为图片
        const image = new Image()
        image.src = canvas.toDataURL("image/png")
        return {
            data: image.src,
            name: name || "BarcodeToImage",
            extension: "png"
        }
    },
    /*************************高德地图需要的方法**************************/
    // 高德地图load
    async mxLoadGaoDeMap(config, successFun, failedFun) {
        let plugins = ['AMap.ToolBar', 'AMap.Scale']
        let conf = {
            key: "a6bfe02f17c041d823e9e01c6b6b4ca6", // 申请好的Web端开发者Key，首次调用 load 时必填
            version: "2.1Beta", // 2.0 指定要加载的 JS API 的版本，缺省时默认为 1.4.15
            plugins
        }
        if (config) {
            for (let i in config) {
                if (i == "version") {
                    conf.version = config.version || conf.version
                } else if (i == "plugins") {
                    conf.plugins = config.plugins ? plugins.concat(config.plugins) : conf.plugins
                } else {
                    conf[i] = config[i]
                }
            }
        }
        window._AMapSecurityConfig = {
            securityJsCode: '3409b94aca245743d5b5c72250ba8503'
        }
        await AMapLoader.load(conf).then((AMap)=>{
            // 生成地图
            successFun && successFun(AMap)
        }).catch(e => {
            console.error("地图创建出错!", e)
            failedFun && failedFun(e)
        })

        /*****
            AMapUI: {
                version: "1.1",
                plugins: ['overlay/SimpleMarker'],

            },
            Loca: {
                version: "2.0"
            }
        ******/
    },
    mxCommonMapTextInfo(map, config, clickCallback, closeCallback) {
        if (!config || !config.text || !config.position) {
            return false
        }
        window.commonMapTextMarkers = window.commonMapTextMarkers || []
        // 默认全部关闭，同时只存在一个
        if (!config.neverRemove) {
            for (let i in window.commonMapTextMarkers) {
                map.remove(window.commonMapTextMarkers[i])
                window.commonMapTextMarkers.splice(i, 1)
            }
        }
        let text = new AMap.Text({
            bubble: config.bubble || false,
            title: config.title || "",
            text: config.text || "",
            topWhenClick: config.topWhenClick || false,
            draggable: config.draggable || false,
            anchor: config.anchor || "bottom-center",
            offset: config.offset || [0, -5],
            position: config.position,
            extData: config.extData || "",
            style: config.style || "",
            zIndex: config.zIndex || 999999
        })
        // 监听判断
        text.on("click", (event) => {
            let txt = event.target.dom.querySelector(".txtClose")
            let handleClick = (ev) => {
                let isCloseClick = txt.contains(ev.target)
                if (isCloseClick) {
                    closeCallback && closeCallback()
                    let index = window.commonMapTextMarkers.findIndex(x => x._amap_id === text._amap_id)
                    map.remove(text)
                    window.commonMapTextMarkers.splice(index, 1)
                } else {
                    // 非关闭的地方执行事件
                    clickCallback && clickCallback()
                }
                document.removeEventListener("click", handleClick)
            }
            document.addEventListener("click", handleClick)
        })
        window.commonMapTextMarkers.push(text)
        map.add(text)
    },
    mxCloseCommonTextInfo(map) {
        window.commonMapTextMarkers && window.commonMapTextMarkers.length > 0 && window.commonMapTextMarkers.forEach(item => {
            map.remove(item)
        })
        window.commonMapTextMarkers = null
    },
    // 随机取颜色
    mxGetRandomColor() {
        let hex = Math.floor(Math.random() * 16777215).toString(16)
        while (hex.length < 6) {
          hex = '0' + hex
        }
        return '#' + hex
    },
    // 设置primary的颜色
    mxSetDefaultPrimaryColor(color) {
        let hsl = convert.hex.hsl(color)
        let darkHsl = [...hsl], 
            light3 = [...hsl], 
            light5 = [...hsl],
            light7 = [...hsl],
            light8 = [...hsl],
            light9 = [...hsl]
            darkHsl[1] -= 40
            darkHsl[2] -= 13
        let space = Math.floor((100 - hsl[2]) / 7)
            light3[2] = hsl[2] + Math.floor(space * 2)
            light5[2] = light3[2] + Math.floor(space * 1.3)
            light7[2] = light5[2] + space
            light8[2] = light7[2] + Math.floor(space * 0.8)
            light9[2] = light8[2] + Math.floor(space * 0.5)
        document.documentElement.style.setProperty('--el-color-primary', color)
        document.documentElement.style.setProperty('--el-color-primary-light-3', `#${convert.hsl.hex(light3)}`)
        document.documentElement.style.setProperty('--el-color-primary-light-5', `#${convert.hsl.hex(light5)}`)
        document.documentElement.style.setProperty('--el-color-primary-light-7', `#${convert.hsl.hex(light7)}`)
        document.documentElement.style.setProperty('--el-color-primary-light-8', `#${convert.hsl.hex(light8)}`)
        document.documentElement.style.setProperty('--el-color-primary-light-9', `#${convert.hsl.hex(light9)}`)
        document.documentElement.style.setProperty('--el-color-primary-dark-2', `#${convert.hsl.hex(darkHsl)}`)
    },
    // 设置页面头部
    mxSetSysPageHeader(item) {
        let route = router.currentRoute.value
        if (route && route.meta && route.meta.isPageHead) {
            let matchs = route.matched.map(x => {
                let temp = {
                    path: x.path,
                    name: x.name,
                    meta: x.meta
                }
                return temp
            })
            let data = {
                title: item && item.title || route.meta.title,
                breadcrumb: item && item.breadcrumb || matchs,
                desc: item && item.desc || route.meta.desc || ""
            }
            store.dispatch("setSysPageHeader", data)
        } else {
            store.dispatch("setSysPageHeader", null)
        }
    },
    // 数字转换为万，并设置单位
    mxTranceWan(num, uint) {
        let item = {
            number: num || 0,
            unit: uint || "度"
        }
        if (num > 10000) {
            item.number = num / 10000
            item.number = item.number.toFixed(2)
            item.unit = "万" + item.unit
        }
        return item
    }
}

export default common